					-- PROYECTO 2 --


--ejercicio 1 --

data Titulo = Duque | Marques | Conde | Vizconde | Baron deriving Show

dama :: Titulo -> String
dama Duque = "Duquesa"
dama Marques = "Marquesa"
dama Conde = "Condesa"
dama Vizconde = "Vizcondesa"
dama Baron = "Baronesa"

-- ejercicio 2 --

type Territorio = String 
type Nombre = String

data Persona = Rey | Noble Titulo Territorio | Caballero Nombre |Aldeano Nombre deriving Show

personaAStr :: Persona -> String
personaAStr Rey = "Su nobleza el rey"
personaAStr (Noble titulo terr) = "El " ++ (show titulo) ++ " de " ++ terr
personaAStr (Caballero nombre) = "Sir " ++ nombre
personaAStr (Aldeano nombre) = nombre

sirs :: [Persona] -> [String]
sirs [] = []
sirs ((Caballero nombre):xs) = nombre : sirs xs
sirs ((Aldeano nombre):xs) = sirs xs
sirs ((Rey):xs) = sirs xs
sirs ((Noble titulo terr):xs) = sirs xs

-- ejercicio 3 --

type Base = Float
type Altura = Float
type Largo = Float
type Diametro = Float

data Figura = Triangulo Base Altura | Rectangulo Base Altura | Linea Largo | Circulo Diametro

area :: Figura -> Float
area (Triangulo base altura) = (base * altura) / 2
area (Rectangulo base altura) = base * altura
area (Linea largo) = error "Las lineas no tienen área..."
area (Circulo diametro) = pi * (diametro / 2) * (diametro / 2)

-- ejercicio 4 --

data ListAssoc a b = Empty | Node a b (ListAssoc a b)

la_lenght :: Integral c => ListAssoc a b -> c
la_lenght Empty = 0
la_lenght (Node a b porAnalizar) = 1 + la_lenght porAnalizar

la_toListPair :: ListAssoc a b -> [(a,b)]
la_toListPair Empty = []
la_toListPair (Node a b resto) = (a,b) : la_toListPair resto

la_search :: Eq a => ListAssoc a b -> a -> Maybe b
la_search Empty a = Nothing
la_search (Node b c porAnalizar) a | b == a = Just c
				   | otherwise = la_search porAnalizar a


-- ejercicio 5 --

data Arbol a = Hoja | Rama (Arbol a) a (Arbol a) deriving Show

aLenght :: Integral b => Arbol a -> b
aLenght Hoja = 0
aLenght (Rama ai a ad) = 1 + aLenght ai + aLenght ad

aCantHojas :: Integral b => Arbol a -> b
aCantHojas Hoja = 1
aCantHojas (Rama ai a ad) = aCantHojas ai + aCantHojas ad

aInc :: Num a => Arbol a -> Arbol a
aInc Hoja = Hoja
aInc (Rama ai a ad) = Rama (aInc ai) (a+1) (aInc ad)

aPersonaAStr :: Arbol Persona -> Arbol String
aPersonaAStr Hoja = Hoja
aPersonaAStr (Rama ai a ad) = Rama (aPersonaAStr ai) (personaAStr a) (aPersonaAStr ad)

aMap :: (a -> b) -> Arbol a -> Arbol b
aMap funcion Hoja = Hoja
aMap funcion (Rama ai a ad) = Rama (aMap funcion ai) (funcion a) (aMap funcion ad)

aInc2 :: Num a => Arbol a -> Arbol a
aInc2 arbol = aMap (+1) arbol

aPersonaAStr2 :: Arbol Persona -> Arbol String
aPersonaAStr2 arbol = aMap (personaAStr) arbol

aSum :: Num a => Arbol a -> a
aSum Hoja = 0
aSum (Rama ai a ad) = a + (aSum ai) + (aSum ad)

aProd :: Num a => Arbol a -> a
aProd Hoja = 1
aProd (Rama ai a ad) = a * (aProd ai) * (aProd ad)

aFold :: (a -> b -> a -> a) -> a -> Arbol b -> a
aFold f z Hoja = z
aFold f z (Rama ai r ad) = f (aFold f z ai ) r (aFold f z ad)

aSum2 :: Num a => Arbol a -> a
aSum2 arbol = aFold (\x y z -> x+y+z) 0 arbol

aProd2 :: Num a => Arbol a -> a
aProd2 arbol = aFold (\x y z -> x*y*z) 1 arbol

aLenght2 :: Integral b => Arbol a -> b
aLenght2 arbol = aFold (\x y z -> x+1+z) 0 arbol

aCantHojas2 :: Integral b => Arbol a -> b
aCantHojas2 arbol = aFold (\x y z -> x+z) 1 arbol

amap2 :: (a -> b) -> Arbol a -> Arbol b
amap2 f arbol = aFold (\x y z -> Rama x (f y) z ) Hoja arbol



-- ejercicio 6 --

data ExprArith a = Num a | Neg (ExprArith a) | Sum (ExprArith a) (ExprArith a) | Prod (ExprArith a) (ExprArith a) deriving Show

eval :: Num a => ExprArith a -> a
eval (Num a) = a
eval (Neg e) = -(eval e)
eval (Sum e d) = (eval e) + (eval d)
eval (Prod e d) = (eval e) * (eval d)


nnf :: Num a => ExprArith a -> ExprArith a
nnf (Num a) = (Num a)
nnf (Neg (Num a)) = Neg (Num a)
nnf (Neg (Neg a)) = nnf a

nnf (Sum a b) = Sum (nnf a) (nnf b)
nnf (Neg (Sum a b)) = nnf (Sum (Neg a) (Neg b))

nnf (Prod a b) = Prod (nnf a) (nnf b)
nnf (Neg (Prod a b)) = nnf (Prod (Neg a) b)






